package net.huashitong.ssydt.provider.common.service;

import com.alibaba.fastjson.JSONObject;
import net.huashitong.ssydt.article.entity.SsArticleArticle;
import net.huashitong.ssydt.article.entity.SsArticleArticleText;
import net.huashitong.ssydt.article.entity.SsArticleType;
import net.huashitong.ssydt.common.constant.CommonConsts;
import net.huashitong.ssydt.common.entity.*;
import net.huashitong.ssydt.common.entity.vo.*;
import net.huashitong.ssydt.exam.entity.SsExamArticleRecord;
import net.huashitong.ssydt.exam.entity.SsExamPaperRecord;
import net.huashitong.ssydt.exam.entity.SsExamQuestion;
import net.huashitong.ssydt.exam.entity.SsExamTestRecord;
import net.huashitong.ssydt.exam.entity.vo.BaseRecord;
import net.huashitong.ssydt.exam.entity.vo.Option;
import net.huashitong.ssydt.exceptions.ServiceException;
import net.huashitong.ssydt.provider.article.service.SsArticleArticleService;
import net.huashitong.ssydt.provider.article.service.SsArticleArticleTextService;
import net.huashitong.ssydt.provider.article.service.SsArticleTypeService;
import net.huashitong.ssydt.provider.comment.service.CommentService;
import net.huashitong.ssydt.provider.comment.vo.CommentVO;
import net.huashitong.ssydt.provider.common.dto.ShareDTO;
import net.huashitong.ssydt.provider.exam.service.*;
import net.huashitong.ssydt.provider.sys.service.SsSysBasService;
import net.huashitong.ssydt.security.utils.UUIDGenerator;
import net.huashitong.ssydt.sys.entity.SsSysBas;
import net.huashitong.user.UserManager;
import net.huashitong.user.http.Result;
import net.huashitong.user.results.User;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @author <a href="mailto:yhy23456@163.com">huiyang.yu</a>
 * @since 2017.08.23
 */
@Service
@Transactional
public class CommonServiceImpl implements CommonService {

    @Autowired
    private SsSysBasService ssSysBasService;
    @Autowired
    private SsCommonBannerService ssCommonBannerService;
    @Autowired
    private SsCommonFeedbackService ssCommonFeedbackService;
    @Autowired
    private SsArticleArticleService ssArticleArticleService;
    @Autowired
    private SsArticleTypeService ssArticleTypeService;
    @Autowired
    private SsExamQuestionService ssExamQuestionService;
    @Autowired
    private SsExamTestRecordService ssExamTestRecordService;
    @Autowired
    private SsExamPaperRecordService ssExamPaperRecordService;
    @Autowired
    private SsExamArticleRecordService ssExamArticleRecordService;
    @Autowired
    private SsCommonMappingService ssCommonMappingService;
    @Autowired
    private SsArticleArticleTextService ssArticleArticleTextService;
    @Autowired
    private UserManager userManager;
    @Autowired
    private CommentService commentService;
    @Autowired
    private ExamService examService;
    @Autowired
    private SsCommonNoticeService ssCommonNoticeService;
    @Autowired
    private SsCommonYearScoreService ssCommonYearScoreService;

    @Override
    public List<AreaVo> provinceList() {
        List<SsSysBas> ssSysBas = ssSysBasService.queryNotTypeByBasType("province");
        List<AreaVo> areaVos = new ArrayList<>();
        for (SsSysBas ssSysBa : ssSysBas) {
            AreaVo areaVo = new AreaVo(ssSysBa);
            areaVos.add(areaVo);
        }
        return areaVos;
    }

    @Override
    public List<AreaVo> cityList(String provinceId) {
        List<SsSysBas> ssSysBas = ssSysBasService.queryNotTypeByBasTypeAndAttr1("city", provinceId);
        List<AreaVo> areaVos = new ArrayList<>();
        for (SsSysBas ssSysBa : ssSysBas) {
            AreaVo areaVo = new AreaVo(ssSysBa);
            areaVos.add(areaVo);
        }
        return areaVos;
    }

    @Override
    public List<AreaVo> countyList(String cityId) {
        List<SsSysBas> ssSysBas = ssSysBasService.queryNotTypeByBasTypeAndAttr1("county", cityId);
        List<AreaVo> areaVos = new ArrayList<>();
        for (SsSysBas ssSysBa : ssSysBas) {
            AreaVo areaVo = new AreaVo(ssSysBa);
            areaVos.add(areaVo);
        }
        return areaVos;
    }

    @Override
    public List<AreasVo> areasList() {
        List<AreaVo> provinces = this.provinceList();
        List<AreasVo> provinceList = new ArrayList<>();
        for (AreaVo province : provinces) {
            List<AreaVo> citys = this.cityList(province.getId());
            List<AreasVo> cityList = new ArrayList<>();
            for (AreaVo city : citys) {
                List<AreaVo> countys = this.countyList(city.getId());
                List<AreasVo> countyList = new ArrayList<>();
                for (AreaVo county : countys) {
                    AreasVo countyVo = new AreasVo(county);
                    countyList.add(countyVo);
                }
                AreasVo cityVo = new AreasVo(city);
                cityVo.setNextList(countyList);
                cityList.add(cityVo);
            }
            AreasVo provinceVo = new AreasVo(province);
            provinceVo.setNextList(cityList);
            provinceList.add(provinceVo);
        }
        return provinceList;
    }

    @Override
    public List<CommonBannerVO> getBannerList() {
        List<SsCommonBanner> ssCommonBanners = ssCommonBannerService.findOrderSequenceAsc();
        List<CommonBannerVO> commonBannerVOS = new ArrayList<>();
        for (SsCommonBanner ssCommonBanner : ssCommonBanners) {
            CommonBannerVO commonBannerVO = new CommonBannerVO(ssCommonBanner);
            commonBannerVOS.add(commonBannerVO);
        }
        return commonBannerVOS;
    }

    @Override
    public void postFeedback(FeedbackVO feedbackVO, String userId) {
        String json = "[]";
        if (feedbackVO.getImageList() != null) {
            json = JSONObject.toJSONString(feedbackVO.getImageList());
        }
        SsCommonFeedback ssCommonFeedback = new SsCommonFeedback();
        ssCommonFeedback.setFeedbackType(feedbackVO.getFeedbackType());
        ssCommonFeedback.setDescribeContent(feedbackVO.getDescribeContent());
        ssCommonFeedback.setImageList(json);
        ssCommonFeedback.setUserId(userId);
        ssCommonFeedbackService.insert(ssCommonFeedback);
    }

    @Override
    public ShareOutVO getShareArticle(Long articleId, String userId, HttpServletRequest request) {
        SsArticleArticle article = ssArticleArticleService.getById(articleId);
        if (article == null) {
            throw new ServiceException("文章不存在");
        }
        SsArticleType type = ssArticleTypeService.getById(article.getArticleTypeId());
        ShareOutVO shareOutVO = new ShareOutVO();
        shareOutVO.setTitle(type.getName());
        shareOutVO.setContent(article.getTitle());
        shareOutVO.setLinkUrl(getLinkUrl(request, CommonConsts.ShareType.ARTICLE, new ShareDTO(userId, articleId)));
        return shareOutVO;
    }


    @Override
    public ShareOutVO getShareQuestion(Long questionId, String userId, HttpServletRequest request) {
        SsExamQuestion ssExamQuestion = ssExamQuestionService.getById(questionId);
        if (ssExamQuestion == null) {
            throw new ServiceException("题目不存在");
        }
        ShareOutVO shareOutVO = new ShareOutVO();
        shareOutVO.setTitle("你敢说自己是学霸？我从时事一点通找道题考考你。");
        shareOutVO.setContent(ssExamQuestion.getQuestion());
        shareOutVO.setLinkUrl(getLinkUrl(request, CommonConsts.ShareType.QUESTION, new ShareDTO(userId, questionId)));
        return shareOutVO;
    }

    @Override
    public ShareOutVO getShareExamReport(String type, Long recordId, String userId, HttpServletRequest request) {
        int correctNumber;
        int questionNumber;
        String examName;
        switch (type) {
            case CommonConsts.ExamType.TEST:
                SsExamTestRecord ssExamTestRecord = ssExamTestRecordService.getById(recordId);
                if (ssExamTestRecord == null) {
                    throw new ServiceException("记录不存在");
                }
                correctNumber = ssExamTestRecord.getCorrectNumber();
                questionNumber = ssExamTestRecord.getQuestionNumber();
                examName = String.format("全真刷题 阶段%d", ssExamTestRecord.getStageNumber());
                break;
            case CommonConsts.ExamType.PAPER:
                SsExamPaperRecord ssExamPaperRecord = ssExamPaperRecordService.getById(recordId);
                if (ssExamPaperRecord == null) {
                    throw new ServiceException("记录不存在");
                }
                correctNumber = ssExamPaperRecord.getCorrectNumber();
                questionNumber = ssExamPaperRecord.getQuestionNumber();
                examName = ssExamPaperRecord.getPaperName();
                break;
            case CommonConsts.ExamType.ARTICLE:
                SsExamArticleRecord record = ssExamArticleRecordService.selectByPrimaryKey(recordId);
                if (record == null) {
                    throw new ServiceException("记录不存在");
                }
                correctNumber = record.getCorrectNumber();
                questionNumber = record.getQuestionNumber();
                examName = record.getTitle();
                break;
            default:
                throw new ServiceException("类型错误");
        }
        BigDecimal correctRate = BigDecimal.valueOf(correctNumber)
                .divide(BigDecimal.valueOf(questionNumber), 4, BigDecimal.ROUND_DOWN);
        BigDecimal correctRatePercentage = correctRate.multiply(BigDecimal.valueOf(100)).setScale(0, BigDecimal.ROUND_DOWN);
        ShareOutVO shareOutVO = new ShareOutVO();
        shareOutVO.setTitle(String.format("我在时事一点通作答中，答对了%s%%的题目。你敢来战吗？", correctRatePercentage));
        shareOutVO.setContent(examName);
        shareOutVO.setLinkUrl(getLinkUrl(request, CommonConsts.ShareType.EXAM_REPORT, new ShareDTO(userId, type, recordId)));
        return shareOutVO;
    }

    @Override
    public String shareForward(String uuid, HttpServletRequest request) {
        String view;
        SsCommonMapping ssCommonMapping = ssCommonMappingService.getByUuid(uuid);
        if (ssCommonMapping == null) {
            view = "no-page";
            return view;
        }
        switch (ssCommonMapping.getShareType()) {
            case CommonConsts.ShareType.ARTICLE:
                view = "article";
                break;
            case CommonConsts.ShareType.QUESTION:
                view = "question";
                break;
            case CommonConsts.ShareType.EXAM_REPORT:
                view = "exam-report";
                break;
            default:
                view = "no-page";
                break;
        }

        request.setAttribute("data", JSONObject.parseObject(ssCommonMapping.getObjectJson(), ShareDTO.class));
        return view;
    }

    @Override
    public Model getShareArticlePage(HttpServletRequest request, Model model) {
        ShareDTO shareDTO = getSsCommonMapping(request);
        String userId = "";
        //文章信息
        SsArticleArticle ssArticleArticle = ssArticleArticleService.selectByPrimaryKey(shareDTO.getRecordId());
        if (ssArticleArticle == null) {
            throw new ServiceException("文章不存在");
        }
        SsArticleArticleText ssArticleArticleText = ssArticleArticleTextService.selectByArticleId(ssArticleArticle.getId());
        //用户信息
        Result<User> rs = userManager.get(ssArticleArticle.getCreateUserId());
        CommentVO.User user = new CommentVO.User();
        if (rs.getCode().equals(Result.Status.SUCCESS)) {
            if (rs.getResults() != null) {
                BeanUtils.copyProperties(rs.getResults(), user);
            } else {
                user.setImageUrl("/dist/img/@2x/head.png");
                user.setNickname("华叔");
            }
        } else {
            user.setImageUrl("/dist/img/@2x/head.png");
            user.setNickname("华叔");
        }
        //相关文章
        List<SsArticleArticle> articleList = ssArticleArticleService.queryLatelyThreeByIdWithArticleTypeId(ssArticleArticle);
        //评论列表
        List<CommentVO> commentList = commentService.getArticleTopFiveHotCommonList(shareDTO.getRecordId(), userId);

        //判断是否有测评
        long articleTypeId = ssArticleArticle.getArticleTypeId();
        boolean isEvaluation = articleTypeId == 3L || articleTypeId == 4L;

        model.addAttribute("article", ssArticleArticle);
        model.addAttribute("articleText", ssArticleArticleText);
        model.addAttribute("user", user);
        model.addAttribute("articleList", articleList);
        model.addAttribute("commentList", commentList);
        model.addAttribute("isEvaluation", isEvaluation);
        return model;
    }


    @Override
    public Model getShareQuestionPage(HttpServletRequest request, Model model) {
        ShareDTO shareDTO = getSsCommonMapping(request);
        SsExamQuestion question = ssExamQuestionService.getById(shareDTO.getRecordId());
        List<Option> options = examService.getOptions(shareDTO.getRecordId());
        model.addAttribute("question", question);
        model.addAttribute("options", options);
        return model;
    }

    @Override
    public Model getShareExamReportPage(HttpServletRequest request, Model model) {
        ShareDTO shareDTO = getSsCommonMapping(request);
        long recordId = shareDTO.getRecordId();
        BaseRecord baseRecord;
        String title;
        switch (shareDTO.getExamType()) {
            case CommonConsts.ExamType.TEST:
                SsExamTestRecord ssExamTestRecord = ssExamTestRecordService.getById(recordId);
                if (ssExamTestRecord == null) {
                    throw new ServiceException("记录不存在");
                }
                baseRecord = setBaseRecord(ssExamTestRecord);
                title = String.format("全真刷题 阶段%d", ssExamTestRecord.getStageNumber());
                break;
            case CommonConsts.ExamType.PAPER:
                SsExamPaperRecord ssExamPaperRecord = ssExamPaperRecordService.getById(recordId);
                if (ssExamPaperRecord == null) {
                    throw new ServiceException("记录不存在");
                }
                baseRecord = setBaseRecord(ssExamPaperRecord);
                title = ssExamPaperRecord.getPaperName();
                break;
            case CommonConsts.ExamType.ARTICLE:
                SsExamArticleRecord record = ssExamArticleRecordService.selectByPrimaryKey(recordId);
                if (record == null) {
                    throw new ServiceException("记录不存在");
                }
                baseRecord = setBaseRecord(record);
                title = record.getTitle();
                break;
            default:
                throw new ServiceException("类型错误");
        }
        model.addAttribute("record", baseRecord);
        model.addAttribute("title", title);
        return model;
    }

    @Override
    public NoticeVO getNotice(String userId) {
        SsCommonNotice ssCommonNotice = ssCommonNoticeService.getFirst();
        if (ssCommonNotice == null) {
            return null;
        }
//        if (StringUtils.isNotBlank(userId)) {
//            //临时处理 回顾2017，活动过时后  删除 start
//            if (userId.length() > 10 && userId.substring(2, 4).compareTo("18") >= 0) {
//                ssCommonNotice = ssCommonNoticeService.selectByPrimaryKey(1L);
//            }
//            //临时处理 回顾2017，活动过时后  删除 end
//            boolean isUserId = ssCommonNotice.getLinkUrl().contains("{userId}");
//            if (isUserId) {
//                String linkUrl = ssCommonNotice.getLinkUrl().replace("{userId}", userId);
//                ssCommonNotice.setLinkUrl(linkUrl);
//            }
//        }
        return new NoticeVO(ssCommonNotice);
    }

    @Override
    public YearScoreVO getYearScore(String userId) {
        SsCommonYearScore ssCommonYearScore = ssCommonYearScoreService.getByUserId(userId);
        if (ssCommonYearScore == null) {
            ssCommonYearScore = new SsCommonYearScore();
            ssCommonYearScore.setQuestionNumber(0);
            ssCommonYearScore.setCorrectNumber(0);
            ssCommonYearScore.setBestNumber(0);
            ssCommonYearScore.setMyCorrectRate(BigDecimal.valueOf(0));
            ssCommonYearScore.setBestDate("00-00-00");
            ssCommonYearScore.setRanking(0);
        }
        YearScoreVO yearScoreVO = new YearScoreVO(ssCommonYearScore);
        Result<User> rs = userManager.get(userId);
        if (rs.getCode().equals(Result.Status.SUCCESS)) {
            yearScoreVO.setNickname(rs.getResults().getNickname());
        } else {
            yearScoreVO.setNickname("");
        }
        return yearScoreVO;
    }


    /**
     * 生成链接地址
     *
     * @param request
     * @param shareType
     * @param dto
     * @return
     */
    private String getLinkUrl(HttpServletRequest request, String shareType, ShareDTO dto) {
        String basePath = getBsePath(request);
        String uuid = UUIDGenerator.uuid2();
        String linkUrl = String.format("%s/api/common/share/%s", basePath, uuid);

        SsCommonMapping ssCommonMapping = new SsCommonMapping();
        ssCommonMapping.setUserId(dto.getUserId());
        ssCommonMapping.setUuid(uuid);
        ssCommonMapping.setShareType(shareType);
        ssCommonMapping.setObjectJson(JSONObject.toJSONString(dto));
        ssCommonMappingService.insertSelective(ssCommonMapping);

        return linkUrl;
    }


    private String getBsePath(HttpServletRequest request) {
        String path = request.getContextPath();
        return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path;
    }


    /**
     * @param request
     * @return
     */
    private ShareDTO getSsCommonMapping(HttpServletRequest request) {
        Object object = request.getAttribute("data");
        ShareDTO shareDTO = null;
        if (object != null && object instanceof ShareDTO) {
            shareDTO = (ShareDTO) object;
        } else {
            throw new ServiceException("非法操作");
        }
        return shareDTO;
    }


    /**
     * 设置基本记录
     *
     * @param record
     * @return
     */
    private BaseRecord setBaseRecord(Object record) {
        BaseRecord baseRecord = new BaseRecord();
        if (record instanceof SsExamTestRecord) {
            SsExamTestRecord ssExamTestRecord = (SsExamTestRecord) record;
            baseRecord.setRecordId(ssExamTestRecord.getId());
            baseRecord.setTestState(ssExamTestRecord.getTestState());
            baseRecord.setQuestionNumber(ssExamTestRecord.getQuestionNumber());
            baseRecord.setFinishNumber(ssExamTestRecord.getFinishNumber());
            baseRecord.setCorrectNumber(ssExamTestRecord.getCorrectNumber());
            baseRecord.setCoefficient(ssExamTestRecord.getCoefficient());
            baseRecord.setCorrectAvgRate(ssExamTestRecord.getCorrectAvgRate());
            baseRecord.setUserTime(ssExamTestRecord.getUserTime());
            baseRecord.setBeatRate(ssExamTestRecord.getBeatRate());
        } else if (record instanceof SsExamPaperRecord) {
            SsExamPaperRecord ssExamPaperRecord = (SsExamPaperRecord) record;
            baseRecord.setRecordId(ssExamPaperRecord.getId());
            baseRecord.setTestState(ssExamPaperRecord.getTestState());
            baseRecord.setQuestionNumber(ssExamPaperRecord.getQuestionNumber());
            baseRecord.setFinishNumber(ssExamPaperRecord.getFinishNumber());
            baseRecord.setCorrectNumber(ssExamPaperRecord.getCorrectNumber());
            baseRecord.setCoefficient(ssExamPaperRecord.getCoefficient());
            baseRecord.setCorrectAvgRate(ssExamPaperRecord.getCorrectAvgRate());
            baseRecord.setUserTime(ssExamPaperRecord.getUserTime());
            baseRecord.setBeatRate(ssExamPaperRecord.getBeatRate());
        } else if (record instanceof SsExamArticleRecord) {
            SsExamArticleRecord ssExamArticleRecord = (SsExamArticleRecord) record;
            baseRecord.setRecordId(ssExamArticleRecord.getId());
            baseRecord.setTestState(ssExamArticleRecord.getTestState());
            baseRecord.setQuestionNumber(ssExamArticleRecord.getQuestionNumber());
            baseRecord.setFinishNumber(ssExamArticleRecord.getFinishNumber());
            baseRecord.setCorrectNumber(ssExamArticleRecord.getCorrectNumber());
            baseRecord.setCoefficient(ssExamArticleRecord.getCoefficient());
            baseRecord.setCorrectAvgRate(ssExamArticleRecord.getCorrectAvgRate());
            baseRecord.setUserTime(ssExamArticleRecord.getUserTime());
            baseRecord.setBeatRate(ssExamArticleRecord.getBeatRate());
        } else {
            throw new ServiceException("记录类型错误");
        }
        BigDecimal correctRate;
        Integer correctNumber = baseRecord.getCorrectNumber();
        if (correctNumber > 0) {
            correctRate = BigDecimal.valueOf(correctNumber)
                    .divide(BigDecimal.valueOf(baseRecord.getQuestionNumber()), 2, BigDecimal.ROUND_DOWN);
        } else {
            correctRate = BigDecimal.valueOf(0.0);
        }
        baseRecord.setCorrectRate(correctRate);
        return baseRecord;
    }
}
